Uploading a file to Dropbox, with OAUTH2

Latest update: February 2018

In this tutorial we will look at how to upload files to Dropbox. This script will upload and save access tokens.

Introduction

  1. Create an Upload folder in FlashAir and set up the file to be uploaded.
  2. Add UPLOAD=1 to the CONFIG file to make the upload function valid.
  3. Specify the Lua script execution method in the CONFIG file referring to Run Lua with FlashAir.

Register your application

The following work must be done on a PC connected to the Internet.

  1. Open Dropbox Developers .
  2. Click "Sign in" at the top right of the screen and log in to your dropbox account.
  3. After logging in, click "My apps" in the left navigation and click "Create apps".
  4. Enter all API settings and click "Create app".
    • An example: "Dropbox API","App folder","Lua Upload"

  5. Once you can create an app, you can get the App key and App secret. App secret is displayed by clicking "Show". Please be careful about handling this information and do not share it with others.
  6. Get the "authorization code" from the following link. Access the following URL from the web browser. Please enter the obtained App key for client_id.
    https://www.dropbox.com/oauth2/authorize?client_id=btbjfXxXxXxXxXx&response_type=code
  7. When the API request approval screen appears, click "Allow".
  8. The API request has been approved. Note the acquired "authorization code".

Let's get started

If the last script to be executed requires re-authentication, the acquired code may have expired, so please get the "authorization code" again.

/DropboxUpload.lua

--[[
FlashAir Lua Dropbox example.

This script uploads and files in a directory to dropbox, using oauth2.
It will store the access token in dropbox_token.txt
--]]
local tokenfile		= "/dropbox_token.txt" 	-- Where to log output on the FA
local folder 		= "/Upload" 		-- What folder to upload files from
local app_key		= "btbjfXxXxXxXxXx"	-- Your Dropbox app's key
local app_secret	= "4k79gXxXxXxXxXx"	-- Your Dropbox app's secret

--NOTE: Remember to authorize your app!
local auth_code 	= "XrfRXkfTNcXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX" -- authorization code

Next, let's get an access token using fa.request.

--[[
requestToken(app key, app secret, authorization code)
requests the oath2 token, using fa.request().
returns the token, or nil on a failure.
--]]
local function requestToken(key, secret, auth_code)
	--Request a token
	message = "grant_type=authorization_code&code="..auth_code.."&client_id="..key.."&client_secret="..secret
	b, c, h = fa.request{
		url = "https://api.dropboxapi.com/oauth2/token",
		method = "POST",
		headers = {["Content-Length"] = string.len(message),
		["Content-Type"] = "application/x-www-form-urlencoded"},
		body = message
	}

	--Decode the response body (json format)
	response = cjson.decode(b)
	access_token = response["access_token"]
	if access_token ~= nil then
		return access_token
	else
		error = response["error_description"]
		print("Failed to get access token. Error: "..c..": "..error)
		return nil
	end
end

Let's prepare two functions to save the acquired token.

Note: When FlashAir is mounted on a PC and the script is being executed, it may not be possible to write the access token file. In that case, please remove FlashAir once and try again.

--[[
These functions simply load or save the access token to/from a file (tokenfile).
--]]
local function saveToken(access_token)
	local file = io.open(tokenfile, "w" )
	file:write(access_token)
	io.close(file)
end
local function loadToken()
	local file = io.open(tokenfile, "r" )
	access_token = nil
	if file then
		access_token = file:read( "*a" )
	end
	return access_token
end

Finally, let's write a function that actually uploads the file. Here, we will also use the fa.request to execute the PUT request.

--[[
	uploadFile(folder, file name, access token)
	Attempts to upload a file to dropbox!
--]]
local function uploadFile(folder, file, access_token)
	file_path=folder .. "/" .. file
	--get the size of the file
	local filesize = lfs.attributes(file_path,"size")
	if filesize ~= nil then
		print("Uploading "..file_path.." size: "..filesize)
	else
		print("Failed to find "..file_path.."... something wen't wrong!")
		return
	end

	--Upload!
	b, c, h = fa.request{
		url = "https://content.dropboxapi.com/2/files/upload",
		method = "POST",
		headers = {["Authorization"] = "Bearer "..access_token,
		["Content-Length"] = filesize,
		["Content-Type"] = "application/octet-stream",
		["Dropbox-API-Arg"] = '{"path":"'..file_path..'","mode":{".tag":"overwrite"}}'},
		body = "<!--WLANSDFILE-->",
		bufsize = 1460*10,
		file=file_path
	}

	print(c)
	print(b)

end

Let's run it! Load saved tokens. If the reading fails, request a token or input authorization code. Then use LuaFileSystem to scan the directory and upload it using the same method from the FTP tutorial.

--Script starts

--Attempt to load a token from the file
token = loadToken()

--See if we loaded one, if not request one
if token == nil then
	--Request an access token
	print("No token found, attempting to request one...")
	token = requestToken(app_key, app_secret, auth_code)

	--Was it successful?
	if token == nil then
		print("Failed to request token, do you need to authorize?")
		print("Auth url: https://www.dropbox.com/oauth2/authorize?client_id="..app_key.."&response_type=code")
	else
		print("New token: "..token)
		saveToken(token)
	end

end

--Before continuing, make sure we have an access token
if token ~= nil then
	print("INIT, with token: "..token)
	-- For each file in folder...
	for file in lfs.dir(folder) do
		-- Get that file's attributes
		attr = lfs.attributes(folder .. "/" .. file)

		-- Don't worry about directories (yet)
		if attr.mode == "file" then
			--Attempt to upload the file!
			uploadFile(folder, file, token)
		end
	end
end

Go to Dropbox and click the name of the application you created.

The uploaded file is displayed.

Sample code

View repository (GitHub)

All sample code on this page is licensed under LGPLv2 or BSD 2-Clause License